package br.com.roteador.usuario;

import java.lang.reflect.InvocationTargetException;

import javax.annotation.PostConstruct;
import javax.inject.Inject;

import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.codec.binary.Base64;

import br.com.caelum.vraptor.Controller;
import br.com.caelum.vraptor.Get;
import br.com.caelum.vraptor.Path;
import br.com.caelum.vraptor.Post;
import br.com.caelum.vraptor.util.test.MockResourceBundle;
import br.com.caelum.vraptor.util.test.MockResult;
import br.com.roteador.component.PasswordEncryptionService;
import br.com.roteador.component.StringUteis;
import br.com.roteador.controller.BasicController;
import br.com.roteador.controller.HomeController;

@Controller
public class UsuarioController extends BasicController {
    @Inject private UsuarioDAO usuarioDAO;
   
    public UsuarioController(MockResult result, MockResourceBundle bundle,
			UsuarioDAO usuarioDAO) {
    	this.result = result;
		this.bundle = bundle;
		this.usuarioDAO = usuarioDAO;
	}

    public UsuarioController(){}
    
	@PostConstruct
    public void init(){
        injetaUsuario();
    }
   
    @Path(value = "/" + USUARIO)
    @Get
    public void usuario() {
        result.include("listaUsuarios", usuarioDAO.recuperaUsuarios());
    }
   
    @Path(value = "/" + USUARIO + "/" + NOVO)
    @Get
    public void novo() {
        result.include(USUARIO, new Usuario());
    }
   
    @Path(value = "/" + USUARIO)
    @Post
    public void editar(String id){
    	if(!StringUteis.isEmpty(id)){
	        Usuario usuario = (Usuario) usuarioDAO.find(Usuario.class, Integer.parseInt(id));
	        result.include(USUARIO, usuario);
    	} else {
    		mensagemErro("erro.ao.recuperar");
    	}
    }
   
    @Path(value = "/"  + USUARIO + "/" + EXCLUIR)
    @Post
    public void excluir(String id){
    	if(!StringUteis.isEmpty(id)){
	        Usuario usuario = (Usuario) usuarioDAO.find(Usuario.class, Integer.parseInt(id));
	        usuarioDAO.remove(usuario);
	        mensagemSucesso("usuario.excluido.sucesso");
    	} else {
    		mensagemErro("erro.ao.excluir");
    	}
        redirect();
    }
   
    @Path(value = "/"  + USUARIO + "/" + GRAVAR)
    @Post
    public void gravar(Usuario usuario){
    	if(usuario == null){
    		mensagemErro("erro.ao.gravar");
    	} else {
    		if(StringUteis.isEmpty(usuario.getNome())){
    			mensagemErro("erro.nome.usuario.obrigatorio");
    		}
    		if(StringUteis.isEmpty(usuario.getEmail())){
    			mensagemErro("erro.email.usuario.obrigatorio");
    		}
    		if(StringUteis.isEmpty(usuario.getSenha())){
    			mensagemErro("erro.senha.usuario.obrigatorio");
    		}
    	}
    	if(resultPossui(ERROR) && resultPossuiConteudo(ERROR)){ redirect(); return;}
        Usuario pre = usuarioDAO.recuperaUsuarioPorEmail(usuario.getEmail());
        if(pre != null){
            Integer id = pre.getId();
            String tipo = pre.getTipo();
            try {
                BeanUtils.copyProperties(pre, usuario);
            } catch (IllegalAccessException e) {
            	mensagemErro("erro.ao.gravar");
            } catch (InvocationTargetException e) {
            	mensagemErro("erro.ao.gravar");
            }
            pre.setId(id);
            pre.setTipo(tipo);
            geraChaveCriptografada(pre);
            usuarioDAO.update(pre);
            mensagemSucesso("usuario.atualizado.sucesso");
        } else {
            usuario.setTipo("U");
            geraChaveCriptografada(usuario);
            usuarioDAO.save(usuario);
            mensagemSucesso("usuario.gravado.sucesso");
        }
        redirect();
    }

	private void geraChaveCriptografada(Usuario usuario) {
		PasswordEncryptionService pes = new PasswordEncryptionService();
		
		try {
			byte[] salt = pes.generateSalt();
			usuario.setChave(Base64.encodeBase64String(salt));
			usuario.setSenha(Base64.encodeBase64String(pes.getEncryptedPassword(usuario.getSenha(), salt)));
		} catch (Exception e) {
			mensagemErro("erro.ao.gravar");
		}
	}
	
	private Boolean regraValidacaoSenha(String senha){
		String pattern = "^(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])(?=.*[@#$%^&+=])(?=\\S+$).{8,}$";
		return senha.matches(pattern);
	}
   
    @Path(value = "/"  + USUARIO + "/gravarSenha")
    @Post
    public void gravarSenha(Usuario usuario){
    	if(usuario != null){
	        Usuario pre = (Usuario) usuarioDAO.find(Usuario.class, usuario.getId());
	        if(pre != null){
	            geraChaveCriptografada(usuario);
	            usuarioDAO.update(pre);
	            mensagemSucesso("senha.alterada.sucesso");
	        } else {
	        	mensagemErro("erro.ao.gravar");
	        }
    	} else {
    		mensagemErro("erro.ao.gravar");
    	}
        result.redirectTo(HomeController.class).login();
    }

    protected void redirect() {
        result.redirectTo(UsuarioController.class).usuario();
    }

}